package com.jt.auth.config;

import com.fasterxml.jackson.databind.ObjectMapper;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.web.authentication.AuthenticationFailureHandler;
import org.springframework.security.web.authentication.AuthenticationSuccessHandler;

import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.HashMap;
import java.util.Map;

/**
 * 建议 方法 在一屏之内
 *
 * @author 金帮嘉诚 @date 2021-08-26 星期四 15:22
 */
@Configuration
public class SecurityConfig extends WebSecurityConfigurerAdapter {
    /**初始化密码加密对象*/
    @Bean
    public BCryptPasswordEncoder passwordEncoder() {
        return new BCryptPasswordEncoder();
    }
    /**配置认证管理器(此对象主要负责对客户端输入的用户信息进行认证),
     * 在其它配置类中会用到这个对象*/
    @Bean
    public AuthenticationManager authenticationManagerBean()
            throws Exception {
        return super.authenticationManagerBean();
    }


    /**在这个方法中定义登录规则
     * 1)对所有请求放行(当前工程只做认证)
     * 2)登录成功信息的返回
     * 3)登录失败信息的返回
     * */
    @Override
    protected void configure(HttpSecurity http) throws Exception {
        //关闭跨域工具
        http.csrf().disable();
        //放行所有请求
        http.authorizeRequests().anyRequest().permitAll();

        http.formLogin()
                .successHandler(successHandler())
                .failureHandler(failureHandler());
    }

    @Bean
    public AuthenticationSuccessHandler successHandler() {
//        return new AuthenticationSuccessHandler() {
//            @Override
//            public void onAuthenticationSuccess(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Authentication authentication) throws IOException, ServletException {
//
//            }
//        };
        return (request, response, authentication) -> {
            //1.构建输出信息对象
            Map<String, Object> map = new HashMap<>();
            map.put("state", 200);
            map.put("message", "login ok");
            //2.转化成json
            //3.
            writeJsonToClient(response, map);

        };
    }

    @Bean
    public AuthenticationFailureHandler failureHandler() {
        return (request, response, e) -> {
            Map<String, Object> map = new HashMap<>();
            map.put("state", 201);
            map.put("message", "login fail");

            writeJsonToClient(response, map);
        };
    }

    //共性代码 以json格式输出对象信息到客户端
    private void writeJsonToClient
    (HttpServletResponse response,
     Object object) throws IOException {
        //1.将对象转换为json
        //将对象转换为json有3种方案:
        //1)Google的Gson-->toJson  (需要自己找依赖)
        //2)阿里的fastjson-->JSON (spring-cloud-starter-alibaba-sentinel)
        //3)Springboot web自带的jackson-->writeValueAsString (spring-boot-starter-web)
        //我们这里借助springboot工程中自带的jackson
        //jackson中有一个对象类型为ObjectMapper,它内部提供了将对象转换为json的方法
        //例如:
        String jsonStr = new ObjectMapper().writeValueAsString(object);
        //3.将json字符串写到客户端
        PrintWriter writer = response.getWriter();
        writer.println(jsonStr);
        writer.flush();
    }
}
